package com.tubang.logistics.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.tubang.logistics.eum.OrderStatusEnum;
import com.tubang.logistics.mapper.LogisticsOrderMapper;
import com.tubang.logistics.service.IStatisticsOrderService;
import com.tubang.logistics.util.DateUtils;
import com.tubang.logistics.util.ExcelUtils;
import com.tubang.logistics.vo.statistics.OrderDataSimpleVO;
import com.tubang.logistics.vo.statistics.OrderExportParamVO;
import com.tubang.logistics.vo.statistics.OrderTableVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

@Service
public class StatisticsOrderServiceImpl implements IStatisticsOrderService {

	@Resource
	private LogisticsOrderMapper logisticsOrderMapper;

	@Override
	public Map<String, OrderDataSimpleVO> getOrderData(Long startTime, Long endTime, String userId) {
		Map<String, OrderDataSimpleVO> result = new HashMap<>();

		Date startDate = new Date(startTime);
		Date endDate = new Date(endTime);
		List<OrderDataSimpleVO> orderDataSimpleVOS = logisticsOrderMapper.getOrderData(startDate, endDate, userId);
		for (OrderDataSimpleVO orderDataSimpleVO : orderDataSimpleVOS) {
			orderDataSimpleVO.setOrderStatusName(OrderStatusEnum.getVal(orderDataSimpleVO.getOrderStatus()).getText());
			result.merge(orderDataSimpleVO.getOrderStatus().toString(), orderDataSimpleVO, (map1, map2) -> orderDataSimpleVO);
		}
		return result;
	}

	@Override
	public Map<String, Object> getBusinessData(Long startTime, Long endTime, String userId) {
		Map<String, Object> result = new HashMap<>();
		List<String> timeList = new ArrayList<>();
		List<String> weightList = new ArrayList<>();
		List<String> countList = new ArrayList<>();
		BigDecimal totalMoney = BigDecimal.ZERO;
		BigDecimal totalWeight = BigDecimal.ZERO;
		Integer count = 0;

		ZoneId zoneId = ZoneId.of("Asia/Shanghai");

		LocalDateTime startLocalDate = new Date(startTime).toInstant().atZone(zoneId).toLocalDateTime();
		LocalDateTime endLocalDate = new Date(endTime).toInstant().atZone(zoneId).toLocalDateTime();
		long between = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);

		Long timeUnit;
		if (0 == between) {
			timeUnit = 4L;
		} else {
			if (between % 6 > 0) {
				timeUnit = (between / 6 + 1) * 24;
			} else {
				timeUnit = between / 6 * 24;
			}
		}
		this.initArraysByDays(timeList, startLocalDate, timeUnit);

		for (int i = 0; i < 6; i++) {
			OrderDataSimpleVO orderDataSimpleVO = logisticsOrderMapper.getBusinessByTimeUnit(Date.from(startLocalDate.atZone(zoneId).toInstant()),
					Date.from(startLocalDate.plusHours(timeUnit).atZone(zoneId).toInstant()), userId);
			weightList.add(null != orderDataSimpleVO.getOrderWeight() ? orderDataSimpleVO.getOrderWeight().toPlainString()
					: BigDecimal.ZERO.toPlainString());
			countList.add(null != orderDataSimpleVO.getOrderNum() ? orderDataSimpleVO.getOrderNum().toString() : null);
			count += orderDataSimpleVO.getOrderNum();
			totalMoney = totalMoney.add(null == orderDataSimpleVO.getOrderMoney() ? BigDecimal.ZERO : orderDataSimpleVO.getOrderMoney());
			totalWeight = totalWeight.add(null == orderDataSimpleVO.getOrderWeight() ? BigDecimal.ZERO : orderDataSimpleVO.getOrderWeight());
			startLocalDate = startLocalDate.plusHours(timeUnit);
		}

		BigDecimal allMoney = logisticsOrderMapper.getAllMoneyByCarrier(userId);

		result.put("time", timeList);
		result.put("price", weightList);
		result.put("count", countList);
		result.put("allMoney", allMoney);
		result.put("totalMoney", totalMoney);
		result.put("totalCount", count);
		result.put("totalWeight", totalWeight);
		return result;
	}

	private void initArraysByDays(List<String> timeList, LocalDateTime startLocalDate, Long timeUnit) {
		DateTimeFormatter dateFormatter;
		if (4L != timeUnit) {
			dateFormatter = DateTimeFormatter.ofPattern("MM.dd");
		} else {
			dateFormatter = DateTimeFormatter.ofPattern("hh");
		}

		for (int i = 0; i < 7; i++) {
			timeList.add(startLocalDate.plusHours(timeUnit * i).format(dateFormatter));
		}
	}

	@Override
	public Map<String, Object> getOrderTable(Long startTime, Long endTime, String userId, Integer orderStatus,
											 boolean carrier, String content, Integer page, Integer rows) {
		Map<String, Object> resultMap = new HashMap<>();
		Map<String, Object> paramMap = new HashMap<>();

		PageHelper.startPage(page, rows);
		paramMap.put("startTime", new Date(startTime));
		paramMap.put("endTime", new Date(endTime));
		paramMap.put("userId", userId);
		paramMap.put("orderStatus", orderStatus);
		paramMap.put("carrier", carrier);
		paramMap.put("content", StringUtils.isNotBlank(content) ? content : null);
		List<OrderTableVO> orderTableVOS = logisticsOrderMapper.getOrderTableByParam(paramMap);
		Page pageBean = (Page) orderTableVOS;

		orderTableVOS.stream().filter(orderTableVO -> !OrderStatusEnum.FINISH.getCode().equals(orderTableVO.getOrderStatus()))
				.forEach(orderTableVO -> orderTableVO.setFinishTime(null));
		OrderDataSimpleVO orderDataSimpleVO = logisticsOrderMapper.getSumByParam(paramMap);

		paramMap.clear();
		paramMap.put("orderTableVOS", orderTableVOS);
		paramMap.put("orderDataSimpleVO", orderDataSimpleVO);
		resultMap.put("result", paramMap);
		resultMap.put("total", pageBean.getTotal());
		return resultMap;
	}

	@Override
	public HSSFWorkbook exportOrderTable(OrderExportParamVO orderExportParamVO) {
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("startTime", new Date(orderExportParamVO.getStartTime()));
		paramMap.put("endTime", new Date(orderExportParamVO.getEndTime()));
		paramMap.put("userId", orderExportParamVO.getUserId());
		paramMap.put("orderStatus", orderExportParamVO.getOrderStatus());
		paramMap.put("carrier", orderExportParamVO.isCarrier());
		paramMap.put("content", StringUtils.isNotBlank(orderExportParamVO.getContent()) ? orderExportParamVO.getContent() : null);
		List<OrderTableVO> orderTableVOS = logisticsOrderMapper.getOrderTableByParam(paramMap);

		orderTableVOS.stream().filter(orderTableVO -> !OrderStatusEnum.FINISH.getCode().equals(orderTableVO.getOrderStatus()))
				.forEach(orderTableVO -> orderTableVO.setFinishTime(null));

		//excel内容
		String[][] excelContent = new String[orderTableVOS.size() + 1][7];

		//表头
		excelContent[0][0] = "订单号";
		if (orderExportParamVO.isCarrier()) {
			excelContent[0][1] = "托运方";
			excelContent[0][2] = "托运方联系电话";
		} else {
			excelContent[0][1] = "承运方";
			excelContent[0][2] = "承运方联系电话";
		}
		excelContent[0][3] = "运量（顿）";
		excelContent[0][4] = "运单金额（元）";
		excelContent[0][5] = "线上结算运费（元）";
		excelContent[0][6] = "运输完成时间";


		//内容
		for (int i = 1; i < orderTableVOS.size() + 1; i++) {
			OrderTableVO orderTableVO = orderTableVOS.get(i - 1);
			excelContent[i][0] = orderTableVO.getOrderSn();
			if (orderExportParamVO.isCarrier()) {
				excelContent[i][1] = orderTableVO.getUserName();
				excelContent[i][2] = orderTableVO.getUserPhone();
			} else {
				excelContent[i][1] = orderTableVO.getCarrier();
				excelContent[i][2] = orderTableVO.getCarrierPhone();
			}

			excelContent[i][3] = null != orderTableVO.getWeight() ? orderTableVO.getWeight().toPlainString() : null;
			excelContent[i][4] = null != orderTableVO.getLogisticMoney() ? orderTableVO.getLogisticMoney().toPlainString() : null;
			excelContent[i][5] = null != orderTableVO.getSettlementMoney() ? orderTableVO.getSettlementMoney().toPlainString() : null;
			excelContent[i][6] = DateUtils.getyyyyMMddHHmmss(orderTableVO.getFinishTime());

		}

		//poi
		return ExcelUtils.createMoreSheetHSSFWorkbook(excelContent);
	}
}
